﻿using JLPT.Models.Objects;
using JLPT.ViewModels;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace JLPT.Controllers
{
    public class QuizController : BaseController
    {
        //
        // GET: /Quiz/

        private const int NO_QUESTION = 10;

        public ActionResult Index()
        {
            
            var listKanjiHistory = from q in db.Questions
                            join h in db.QuizHistories on q.Id equals h.QuestionId
                            where q.LevelId == 3 && q.TypeId == 6 // N3 & Kanji
                            select q;
            var listKanji = db.Questions.Where(x => x.LevelId == 3 && x.TypeId == 6);

            var listFavoriteKanji = from q in db.Questions
                                    join h in db.QuizHistories on q.Id equals h.QuestionId
                                    where q.LevelId == 3 && q.TypeId == 6 && h.Favourite == true // N3 & favourite
                                    select q;

            var listVocHistory = from q in db.Questions
                            join h in db.QuizHistories on q.Id equals h.QuestionId
                            where q.LevelId == 3 && q.TypeId == 7 // N3 & Voc
                            select q;
            var listVoc = db.Questions.Where(x => x.LevelId == 3 && x.TypeId == 7);

            var listGramHistory = from q in db.Questions
                          join h in db.QuizHistories on q.Id equals h.QuestionId
                          where q.LevelId == 3 && q.TypeId == 8 // N3 & Gram
                          select q;
            var listGram = db.Questions.Where(x => x.LevelId == 3 && x.TypeId == 8);

           

            ViewBag.PercentKanji = string.Format("{0}/{1}", listKanjiHistory.ToList().Count(), listKanji.ToList().Count());
            ViewBag.PercentVoc = string.Format("{0}/{1}", listVocHistory.ToList().Count(), listVoc.ToList().Count());
            ViewBag.PercentGram = string.Format("{0}/{1}", listGramHistory.ToList().Count(), listGram.ToList().Count());
            ViewBag.NoFavorite = listFavoriteKanji.ToList().Count();

            return View();
        }

        public ActionResult Test(string level, string type, string favourite)
        {
            
            bool isFavorite = false;
            if (!string.IsNullOrEmpty(favourite))
            {
                isFavorite = (favourite.Equals("favourite"));
            }
            
            var listHis = db.Questions.Where(x => db.QuizHistories.Where(a => a.Times > 0)
                                              .Select(b => b.QuestionId)
                                              .Contains(x.Id) && x.Level.Name.Equals(level) && x.Type.Name.Equals(type))// question is exist in history
                                              .OrderBy(x => Guid.NewGuid())
                                              .Take(NO_QUESTION);
            //List favorite
            var listFavorite = db.Questions.Where(x => db.QuizHistories.Where(a => a.Favourite ==true)
                                              .Select(b => b.QuestionId)
                                              .Contains(x.Id) && x.Level.Name.Equals(level) && x.Type.Name.Equals(type))// question is exist in history
                                              .OrderBy(x => Guid.NewGuid())
                                              .Take(NO_QUESTION);

            var listQues = db.Questions.Where(x => !db.QuizHistories
                                            .Select(b => b.QuestionId)
                                            .Contains(x.Id) && x.Level.Name.Equals(level) && x.Type.Name.Equals(type)) // question is not exist in history
                                            .OrderBy(x => Guid.NewGuid())
                                            .Take(NO_QUESTION);

            //Union 2 list
            IList<Question> list;
            if (isFavorite)
            {
                list = listFavorite.ToList();
            }
            else {
                list = listHis.Union(listQues).OrderBy(x => Guid.NewGuid()).Take(NO_QUESTION).ToList();
            }

            //random sub question
            foreach (Question question in list)
            {
                question.QuestionSubs = question.QuestionSubs.OrderBy(x => Guid.NewGuid()).ToList();
                foreach (var sub in question.QuestionSubs)
                {
                    sub.QuestionDetails = sub.QuestionDetails.OrderBy(x => Guid.NewGuid()).ToList();
                }
            }

            TempData["QuestionList"] = list;

            return View(list);
        }

        [HttpPost]
        public ActionResult Favorite(QuizHistory model)
        {
            bool isFavorite = false;

            var quizDB = db.QuizHistories.First(i => i.QuestionId == model.QuestionId);
            // New entity
            if (quizDB != null)
            {
                isFavorite = !model.Favourite;

                model = quizDB;
                model.Favourite = isFavorite;
                db.SaveChanges();
            }
            
            return Json(new { favorite = isFavorite });
        }

        [HttpPost]
        public ActionResult Test(IList<Question> model)
        {
            int noWrong = 0;

            List<Question> questionList = (List<Question>)TempData["QuestionList"];
            TempData["QuestionList"] = questionList;

            foreach (Question question in model)
            {
                bool flag = true;

                foreach (QuestionSub sub in question.QuestionSubs)
                {
                    List<QuestionDetail> list = GetDetail(sub.Id);

                    //update selected
                    foreach (Question questionDB in questionList)
                    {
                        foreach (QuestionSub subDB in questionDB.QuestionSubs)
                        {
                            if (sub.Id.Equals(subDB.Id))
                            {
                                subDB.SelectedAnswer = sub.SelectedAnswer;
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(sub.SelectedAnswer))
                    {
                        if (!Calculate(list, int.Parse(sub.SelectedAnswer)))
                        {
                            if (flag)
                                noWrong++;
                            flag = false;
                        }
                    }
                }
                QuizHistory quiz = new QuizHistory { QuestionId = question.Id };
                InsertHistory(quiz, flag);
            }

            if (ModelState.IsValid)
            {
                TempData["NoRight"] = model.Count() - noWrong;
                TempData["Percent"] = (model.Count() - noWrong) * 100 / model.Count();
                TempData["Total"] = model.Count();

                TempData["QuestionList"] = questionList;
                return RedirectToAction("Result");
            }
            else
            {
                ViewBag.Error = true;
                return View(questionList);
            }
        }

        public ActionResult Result()
        {
            List<Question> questionList = (List<Question>)TempData["QuestionList"];
            TempData["QuestionList"] = questionList;

            ViewBag.NoRight = TempData["NoRight"];
            ViewBag.Percent = TempData["Percent"];
            ViewBag.Total = TempData["Total"];
            TempData["NoRight"] = ViewBag.NoRight;
            TempData["Percent"] = ViewBag.Percent;
            TempData["Total"] = ViewBag.Total;

            return View(questionList);
        }

        #region Private methods

        private void InsertHistory(QuizHistory quiz, bool isRight)
        {
            var quizDB = db.QuizHistories.FirstOrDefault(i => i.QuestionId == quiz.QuestionId);
            // New entity
            if (quizDB == null)
            {
                if (!isRight)
                    quiz.Times = 1;
                else
                    quiz.Times = 0;

                quiz.NoTest = 1;
                quiz.CreatedDate = DateTime.Now;
                db.QuizHistories.Add(quiz);
                db.SaveChanges();
            }
            // Existing entity
            else
            {
                quiz = db.QuizHistories.First(i => i.QuestionId == quiz.QuestionId);

                //wrong
                if (!isRight)
                    quiz.Times = quizDB.Times + 1;
                else if (isRight && quizDB.Times > 0)
                    quiz.Times = quizDB.Times - 1;
                else
                    quiz.Times = 0;

                quiz.NoTest = quiz.NoTest + 1;
                quiz.UpdatedDate = DateTime.Now;
                db.SaveChanges();
            }
        }

        private bool Calculate(List<QuestionDetail> list, int answerId)
        {
            bool flag = false;
            QuestionDetail detail = (from aa in list
                                     where aa.Id == answerId
                                     select aa).FirstOrDefault();
            if (detail.IsRight)
            {
                flag = true;
            }

            return flag;
        }

        private List<QuestionDetail> GetDetail(int subId)
        {
            var list = db.QuestionDetails.Where(x => x.QuestionSubId == subId);

            //list = (from t in list
            //        orderby t.Id
            //        select t).OrderBy(x => Guid.NewGuid()).ToList();
            return list.ToList();
        }
        #endregion
    }
}
